import * as THREE from "three";
import { CSS3DRenderer, CSS3DObject } from "three/examples/jsm/renderers/CSS3DRenderer";

export default class LabelSystem {
  constructor(scene, camera, config) {
    this.scene = scene;
    this.camera = camera;
    this.config = config;
    this.labels = new Map();
    this.renderer = this.initCSS3DRenderer();
    this.frustum = new THREE.Frustum();
    this.projScreenMatrix = new THREE.Matrix4();
    this.visibleLabels = new Set();
  }

  initCSS3DRenderer() {
    const renderer = new CSS3DRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.domElement.style.position = "absolute";
    renderer.domElement.style.top = "0";
    renderer.domElement.style.pointerEvents = "none";
    renderer.domElement.style.zIndex = "100";
    return renderer;
  }

  addLabelsForMap(map) {
    map.children.forEach((areaGroup, index) => {
      const center = this.calculateGeometryCenter(areaGroup);
      if (center) {
        this.addLabel(areaGroup.properties, center, index);
      }
    });
  }

  addLabel(content, position, id) {
    const label = this.createLabel(content);
    label.position.copy(position);
    label.position.z += 15; // 提高标签高度
    label.userData.id = id;
    this.scene.add(label);
    this.labels.set(id, label);
    return label;
  }

  createLabel(content) {
    const div = document.createElement('div');
    div.className = 'three-label';
    div.textContent = content;
    div.style.cssText = `
      color: #ffffff;
      font-family: ${this.config.label?.fontFamily || 'Arial, sans-serif'};
      font-size: ${this.config.label?.fontSize || '12px'};
      font-weight: bold;
      padding: 2px 6px;
      background: rgba(0, 0, 0, 0.6);
      border-radius: 3px;
      text-shadow: 0 0 3px #000000;
      transform: translate(-50%, -50%);
    `;
    return new CSS3DObject(div);
  }

  update() {
    this.updateFrustum();
    this.updateLabelVisibility();
    this.renderer.render(this.scene, this.camera);
  }

  updateFrustum() {
    this.projScreenMatrix.multiplyMatrices(
      this.camera.projectionMatrix,
      this.camera.matrixWorldInverse
    );
    this.frustum.setFromProjectionMatrix(this.projScreenMatrix);
  }

  updateLabelVisibility() {
    this.visibleLabels.clear();
    
    this.labels.forEach((label, id) => {
      const inFrustum = this.frustum.containsPoint(label.position);
      label.element.style.display = inFrustum ? '' : 'none';
      
      if (inFrustum) {
        this.visibleLabels.add(id);
      }
    });
  }

  calculateGeometryCenter(group) {
    const box = new THREE.Box3().setFromObject(group);
    if (box.isEmpty()) return null;
    
    const center = new THREE.Vector3();
    box.getCenter(center);
    return center;
  }

  updateRendererSize(width, height) {
    this.renderer.setSize(width, height);
  }

  dispose() {
    this.labels.forEach(label => {
      if (label.element && label.element.parentElement) {
        label.element.parentElement.removeChild(label.element);
      }
      this.scene.remove(label);
    });
    this.labels.clear();
    
    if (this.renderer.domElement.parentElement) {
      this.renderer.domElement.parentElement.removeChild(this.renderer.domElement);
    }
  }
}